package com.rinoiot.weather.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rinoiot.weather.entity.BaseCityEntity;
import com.rinoiot.weather.entity.MojiWeatrherEntity;
import com.rinoiot.weather.entity.Vo.CurrentWeatherVo;
import com.rinoiot.weather.entity.query.WeatherQueryParam;
import com.rinoiot.weather.mapper.BaseCityMapper;
import com.rinoiot.weather.service.CurrentWeatherService;
import com.rinoiot.weather.utils.GeoUtil;
import com.rinoiot.weather.utils.HttpUtils;
import com.rinoiot.weather.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@ConditionalOnProperty(prefix = "weather",name = "dataSource",havingValue = "MOJI")
public class MojiWeatherServiceImpl implements CurrentWeatherService {

    private static final String MOJI_WEAHTER = "mojiWeather";

    private final RedisUtil redisUtil;

    private final GeoUtil geoUtil;

    private final BaseCityMapper baseCityMapper;

    private static final String BASE_URL = "https://apifreelat.market.alicloudapi.com";
    private static final String CITY_BASE_URL = "https://freecityid.market.alicloudapi.com";

    @Value("${moji.key}")
    private String key;

    public MojiWeatherServiceImpl(RedisUtil redisUtil, GeoUtil geoUtil, BaseCityMapper baseCityMapper) {
        this.redisUtil = redisUtil;
        this.geoUtil = geoUtil;
        this.baseCityMapper = baseCityMapper;
    }

    @Override
    public CurrentWeatherVo getCurrentWeather(WeatherQueryParam param) {
        if (!StringUtils.isEmpty(param.getCityName())) {
            return getCurrentWeatherVoByCity(param);
        } else if (!ObjectUtils.isEmpty(param.getLat()) && !ObjectUtils.isEmpty(param.getLon())){
            return getCurrentWeatherVoByCoord(param);
        }
        return new CurrentWeatherVo();
    }

    // 向墨迹 发送请求获取天气数据 根据经纬度
    private CurrentWeatherVo getCurrentWeatherVoByCoord(WeatherQueryParam param) {
        Object weather = null;
        try {
            GeoResults<RedisGeoCommands.GeoLocation<String>> pointRadius =
                    geoUtil.getPointRadius(MOJI_WEAHTER, param.getLon(), param.getLat(), 5);
            if (!ObjectUtils.isEmpty(pointRadius) && !CollectionUtils.isEmpty(pointRadius.getContent())) {
                String name = pointRadius.getContent().get(0).getContent().getName();
                weather = redisUtil.get(name);
            }
        } catch (Exception e) {
            log.warn("redis 读取异常");
        }

        if (!ObjectUtils.isEmpty(weather)) {
            try {
                CurrentWeatherVo currentWeatherVo = JSON.parseObject((String) weather, CurrentWeatherVo.class);
                // 时间间隔大于30分钟 返回数据
                if (System.currentTimeMillis() - currentWeatherVo.getCreateTime() < 30 * 60 * 1000) {
                    return currentWeatherVo;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // String host = "https://aliv8.data.moji.com";
        // String path = "/whapi/json/aliweather/condition";

//        String host = "https://apifreelat.market.alicloudapi.com";
        String path = "/whapi/json/aliweather/briefcondition";

        String method = "POST";
        String appcode = key;
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("lat", String.valueOf(param.getLat()));
        bodys.put("lon", String.valueOf(param.getLon()));
        bodys.put("token", "a231972c3e7ba6b33d8ec71fd4774f5e");


        try {
            /*
              重要提示如下:
              HttpUtils请从
              https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
              下载

              相应的依赖请参照
              https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(BASE_URL, path, method, headers, querys, bodys);

//            System.out.println(response.toString());
            // 获取response的body
            // System.out.println(EntityUtils.toString(response.getEntity()));
            String s = EntityUtils.toString(response.getEntity());
            MojiWeatrherEntity mojiWeatrherEntity = JSON.parseObject(s, MojiWeatrherEntity.class);
            CurrentWeatherVo currentWeatherVo = mojiWeatrherEntity.trans();
            try {
                redisUtil.set(currentWeatherVo.getCityName().toLowerCase(), JSON.toJSONString(currentWeatherVo));
                geoUtil.geoAdd(MOJI_WEAHTER,param.getLon(),param.getLat(),currentWeatherVo.getCityName().toLowerCase());
            } catch (Exception e) {
                log.warn("redis 写入异常");
            }
            return currentWeatherVo;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 根据cityId获取 或者 根据cityName获取
     */
    private CurrentWeatherVo getCurrentWeatherVoByCity(WeatherQueryParam param) {
        BaseCityEntity cityEntity = null;
        if (!ObjectUtils.isEmpty(param.getCityId())) {
            cityEntity = getCityById(param.getCityId());
        } else if (!StringUtils.isEmpty(param.getCityName())){
            cityEntity = getCityByName(param.getCityName());
        }
        Object weather;
        if (!ObjectUtils.isEmpty(cityEntity)) {
            try {
                weather = redisUtil.get(cityEntity.getMunicipalName());
                if (!ObjectUtils.isEmpty(weather)) {
                    CurrentWeatherVo currentWeatherVo = JSON.parseObject((String) weather, CurrentWeatherVo.class);
                    // 时间间隔大于30分钟 返回数据
                    if (System.currentTimeMillis() - currentWeatherVo.getCreateTime() < 30 * 60 * 1000) {
                        return currentWeatherVo;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        String path = "/whapi/json/alicityweather/briefcondition";
        String method = "POST";
        String appcode = key;
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();

        if (!ObjectUtils.isEmpty(cityEntity)) {
            bodys.put("cityId", String.valueOf(cityEntity.getId()));
        } else {
            throw new IllegalArgumentException("未找到对应城市");
        }

        bodys.put("token", "46e13b7aab9bb77ee3358c3b672a2ae4");
        try {
            HttpResponse response = HttpUtils.doPost(CITY_BASE_URL, path, method, headers, querys, bodys);
            String s = EntityUtils.toString(response.getEntity());
            MojiWeatrherEntity mojiWeatrherEntity = JSON.parseObject(s, MojiWeatrherEntity.class);
            CurrentWeatherVo currentWeatherVo = mojiWeatrherEntity.trans();
            try {
                redisUtil.set(currentWeatherVo.getCityName().toLowerCase(), JSON.toJSONString(currentWeatherVo));
            } catch (Exception e) {
                log.info("redis 写入异常");
            }
            return currentWeatherVo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // cityId 相关
    public BaseCityEntity getCityByName(String cityName) {
        QueryWrapper<BaseCityEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(BaseCityEntity::getMunicipalName, cityName).or().like(BaseCityEntity::getMunicipalNameEn, cityName);
        List<BaseCityEntity> baseCityEntities = baseCityMapper.selectList(queryWrapper);
        if (baseCityEntities.size() > 0) {
            return baseCityEntities.get(0);
        }
        return null;
    }

    public BaseCityEntity getCityById(String cityId) {
        QueryWrapper<BaseCityEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BaseCityEntity::getId, cityId);
        return baseCityMapper.selectOne(queryWrapper);
    }
}
